/*
 * @Description: StringUtil
 * @Author: zhaokun
 * @Date: 2022-01-07 15:30:37
 * @LastEditTime: 2022-01-10 15:16:04
 * @FilePath: \user\common\nwString.go
 */
package common

import (
	"strings"
	"sync"
	"time"

	uuid "github.com/go-basic/uuid"
)

const (
	workerBits  uint8 = 10
	numberBits  uint8 = 12
	workerMax   int64 = -1 ^ (-1 << workerBits)
	numberMax   int64 = -1 ^ (-1 << numberBits)
	timeShift   uint8 = workerBits + numberBits
	workerShift uint8 = numberBits
	startTime   int64 = 1525705533000 // 如果在程序跑了一段时间修改了epoch这个值 可能会导致生成相同的ID
)

type StringUtil interface {
	SnowFlake() int64
}

type nwStringUtil struct {
	mu        sync.Mutex
	timestamp int64
	workerId  int64
	number    int64
}

func NewNwStringUtil() *nwStringUtil {
	return &nwStringUtil{}
}

func (stringUtil *nwStringUtil) SnowFlake() int64 {
	stringUtil.mu.Lock()
	defer stringUtil.mu.Unlock()
	now := time.Now().UnixNano() / 1e6
	if stringUtil.timestamp == now {
		stringUtil.number++
		if stringUtil.number > numberMax {
			for now <= stringUtil.timestamp {
				now = time.Now().UnixNano() / 1e6
			}
		}
	} else {
		stringUtil.number = 0
		stringUtil.timestamp = now
	}
	ID := int64((now-startTime)<<timeShift | (stringUtil.workerId << workerShift) | (stringUtil.number))
	return ID
}

func (stringUtil *nwStringUtil) UUID() string {
	u1 := uuid.New()
	return u1
}

func (stringUtil *nwStringUtil) SimpleUUID() string {
	u1 := uuid.New()
	u1 = strings.Replace(u1, "-", "", -1)
	return u1
}
